package com.D5Power.scene
{
	import com.D5Power.Controler.CharacterControler;
	import com.D5Power.Controler.NCharacterControler;
	import com.D5Power.Controler.Perception;
	import com.D5Power.Objects.BuildingObject;
	import com.D5Power.Objects.CharacterObject;
	import com.D5Power.Objects.Effects.BulletObject;
	import com.D5Power.Objects.Effects.NoticeEffect;
	import com.D5Power.Objects.GameObject;
	import com.D5Power.Objects.NCharacterObject;
	import com.D5Power.Render.Render;
	import com.D5Power.Render.RenderCharacter;
	import com.D5Power.Render.RenderEffect;
	import com.D5Power.Render.RenderNCharacter;
	import com.D5Power.Render.RenderStatic;
	import com.D5Power.basic.GraphicsResource;
	import com.D5Power.basic.ResourcePool;
	import com.D5Power.utils.AvatarData;
	import com.D5Power.utils.AvatarData_RO;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Scene;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	public class D5Scene extends BaseScene
	{
		/**
		 * 感知器
		 */
		public var perc:Perception;
		
		/**
		 * 建筑渲染器
		 */ 
		protected var render_building:RenderStatic;
		/**
		 * NPC渲染器
		 */ 
		protected var render_npc:RenderNCharacter;
		/**
		 * 角色渲染器
		 */
		protected var render_pc:RenderCharacter;
		/**
		 * 效果渲染器
		 */ 
		protected var render_effect:RenderEffect;

		/**
		 * 
		 * @param	stg				主场景引用
		 * @param	startQuadTree	是否启用四叉树优化
		 */ 
		public function D5Scene(stg:Stage,startQuadTree:Boolean=true)
		{
			super(stg);
			setMap();
			
			perc = new Perception(this);
			Global.resPool = new ResourcePool();
			
			render_effect = new RenderEffect();
			render_effect.d_buffer = effectBuffer;
			
			render_npc = new RenderNCharacter();
			render_npc.d_buffer = doubleBuffer;
			
			render_pc = new RenderCharacter();
			render_pc.d_buffer = doubleBuffer;
			
			render_building = new RenderStatic();
			render_building.d_buffer=doubleBuffer;
			
			_isReady=true;
			
			notice_start = NoticeEffect.STARTY;
		}
		
		/**
		 * 创建NPC
		 * @param	s			位图资源名
		 * @param	resname		缓冲池资源名
		 * @param	name		NPC姓名
		 * @param	pos			目前所在位置
		 * @param	dirConfig	方向配置参数，若为NULL，则为静态1帧
		 */
		public function createNPC(s:String,resname:String,name:String='',pos:Point=null,dirConfig:Object=null):NCharacterObject
		{
			
			var res:GraphicsResource;
			if(dirConfig==null)
			{
				res = new GraphicsResource(null,resname);
			}else{
				res = new GraphicsResource(null,resname,dirConfig.frameTotal,dirConfig.frameLayer,dirConfig.fps,dirConfig.mirror);
			}

			res.addLoadResource(['asset/map/map'+Map.mapid+'/npc/'+s]);
			
			var ctrl:NCharacterControler = new NCharacterControler(perc);
			var npc:NCharacterObject = new NCharacterObject(ctrl);
			npc.render = render_npc;
			npc.graphics=res;
			npc.setName(name);
			
			if(pos!=null) npc.setPos(pos.x,pos.y);
			
			addNCtrl(ctrl,npc.uid);
			addObject(npc);
			
			return npc;
		}
		
		/**
		 * 创建其他用户
		 * 由于不具备通用性。本方法需要在实际的项目中自行实现
		 */ 
		public function createOtherPlayer(s:AvatarData,name:String='',uid:uint = 0,pos:Point=null):NCharacterObject
		{
			return null;
		}
		
		/**
		 * 创建建筑
		 * @param	resList
		 * @param	pos		目前所在位置
		 */ 
		public function createBuilding(resource:String,resname:String,pos:Point=null):BuildingObject
		{
			var res:GraphicsResource = new GraphicsResource(null,resname);
			res.addLoadResource([resource]);
			
			var house:BuildingObject = new BuildingObject(this);
			house.render = render_building;
			house.graphics = res;
			
			if(pos!=null) house.setPos(pos.x,pos.y);
			
			addObject(house);
			
			return house;
		}
		
		/**
		 * 创建玩家
		 * @param	s		位图资源
		 * @param	name	玩家姓名
		 * @param	pos		目前所在位置
		 * @param	ctrl	专用控制器，如果为空，则使用默认的角色控制器
		 */ 
		public function createPlayer(s:AvatarData,resname:String,name:String='',pos:Point=null,ctrl:CharacterControler=null):void
		{
			if(player!=null) return;
			
			
			
			var res:GraphicsResource = new GraphicsResource(s,resname,s.Frame,s.Action,Global.FPS,true);
			
			if(ctrl==null) ctrl = new CharacterControler(perc);
			player = new CharacterObject(ctrl);
			player.render=render_pc;
			player.graphics=res;
			player.setName(name);
			if(pos!=null) player.setPos(pos.x,pos.y);
			setPlayerCtrl(ctrl);
			
			addObject(player);
		}
		
		/**
		 * 向场景中增加子弹
		 * @param	bitmap	子弹素材
		 * @param	b		子弹对象
		 */ 
		public function createBullet(bitmap:BitmapData,b:BulletObject,resname:String):void
		{
			b.graphics = new GraphicsResource(bitmap,resname);
			createEffect(b);
		}
		
		/**
		 * 创建效果
		 * @param	b					要创建的效果
		 * @param	checkView			创建时是否检测视口，若为false，则无条件添加。否则，物品必须在视野范围内才会添加
		 * @param	userEffectBuffer	是否使用EFFECT缓存
		 */ 
		public function createEffect(b:GameObject,checkView:Boolean=false,useEffectBuffer:Boolean=false):void
		{
			if(checkView && !Map.cameraView.containsPoint(b.Pos))
			{
				b = null;
				return;
			}
			
			b.render=useEffectBuffer ? render_effect : render_building;
			addObject(b);
		}
		
		/**
		 * 创建公告
		 * @param	s		公告内容
		 * @param	config	公告样式控制Object @see com.D5Power.Objects.Effects.NoticeEffect
		 */ 
		public function createNotice(s:String,config:Object=null):void
		{
			var b:NoticeEffect = new NoticeEffect(this,s,closeNotice,config);
			b.render = render_building;
			b.Pos.y = notice_start;
			notice_start+=b.graphics.frameHeight;
			if(notice_start>Global.H*.8) notice_start = 100;
			b.Pos.x = int((Global.W-b.graphics.frameWidth)/2);
			notice_list.push(b);
			
		}
		
		/**
		 * 关闭公告
		 */ 
		public function closeNotice(obj:NoticeEffect):void
		{
			var i:int = notice_list.indexOf(obj);
			if(i!=-1)
			{
				notice_start-=obj.graphics.frameHeight;
				notice_list.splice(i,1);
			}
			
		}
		
		/**
		 * 保持一定的剩余数量关闭公告
		 * @param	num	需要剩余的公告数量
		 */ 
		public function closeNoticeByNum(num:uint=3):void
		{
			for each(var obj:NoticeEffect in notice_list)
			{
				if(notice_list.length<num) break;
				closeNotice(obj);
			}
			notice_start = NoticeEffect.STARTY;
			for each(obj in notice_list)
			{
				obj.Pos.y = notice_start;
				notice_start+=obj.graphics.frameHeight;
			}
		}
	}
}